import tkinter as tk
from tkinter import filedialog, messagebox, ttk
import os
import chardet
import sys
import webbrowser  # 添加到文件顶部的导入语句中
import subprocess  # 添加到文件顶部的导入语句中
import time  # 添加到文件顶部的导入语句中
from icon_data import get_icon_file  # 添加到文件顶部

class TextLineNumbers(tk.Canvas):
    def __init__(self, *args, **kwargs):
        self.text_fg = kwargs.pop('line_number_fg', 'gray')  # 获取并移除颜色参数
        tk.Canvas.__init__(self, *args, **kwargs)
        self.textwidget = None

    def attach(self, text_widget):
        self.textwidget = text_widget

    def redraw(self, *args):
        """重绘行号"""
        self.delete("all")

        i = self.textwidget.index("@0,0")
        while True:
            dline = self.textwidget.dlineinfo(i)
            if dline is None: break
            y = dline[1]
            linenum = str(i).split(".")[0]
            self.create_text(
                self.winfo_width()/2,  # x坐标居中
                y + dline[3]/2,        # y坐标居中（行高的中点）
                text=linenum,
                fill=self.text_fg,     # 使用保存的颜色
                anchor="center",        # 文本居中对齐
                font=("Consolas", 9)   # 设置字体和大小
            )
            i = self.textwidget.index("%s+1line" % i)

class CustomText(tk.Text):
    def __init__(self, *args, **kwargs):
        tk.Text.__init__(self, *args, **kwargs)

        self._orig = self._w + "_orig"
        self.tk.call("rename", self._w, self._orig)
        self.tk.createcommand(self._w, self._proxy)

    def _proxy(self, *args):
        try:
            cmd = (self._orig,) + args
            result = self.tk.call(cmd)

            if (args[0] in ("insert", "delete", "replace")):
                self.event_generate("<<Change>>")
            if (args[0] in ("insert", "delete", "replace", "yview", "xview")):
                self.event_generate("<<LineNumbers>>")

            return result
        except Exception:
            return ""

class Notepad:
    def __init__(self, root):
        self.root = root
        self.root.title("码界轩记事本")
        self.root.geometry("800x600")
        
        # 设置窗口在屏幕中央
        self.center_window()
        
        # 设置窗口图标
        try:
            icon_path = get_icon_file()
            self.root.iconbitmap(icon_path)
        except:
            pass  # 如果设置图标失败，就使用默认图标
        
        # 设置主题颜色
        self.bg_color = "#f5f5f5"  # 浅灰色背景
        self.text_bg = "#ffffff"   # 白色文本区域
        self.text_fg = "#333333"   # 深灰色文字
        self.line_number_bg = "#e8e8e8"  # 行号背景色
        self.line_number_fg = "#999999"  # 行号文字颜色
        
        # 设置窗口和主框架背景色
        self.root.configure(bg=self.bg_color)
        self.main_frame = tk.Frame(self.root, bg=self.bg_color)
        self.main_frame.pack(expand=True, fill='both', padx=2, pady=2)
        
        # 创建文本区域和行号的容器
        self.text_frame = tk.Frame(self.main_frame, bg=self.bg_color)
        self.text_frame.pack(expand=True, fill='both', padx=2, pady=(2, 0))
        
        # 创建行号显示区域
        self.line_numbers = TextLineNumbers(
            self.text_frame, 
            width=30, 
            bg=self.line_number_bg,
            line_number_fg=self.line_number_fg  # 传入行号颜色
        )
        self.line_numbers.pack(side=tk.LEFT, fill=tk.Y)
        
        # 创建主文本区域
        self.text_area = CustomText(
            self.text_frame,
            undo=True,
            wrap=tk.WORD,  # 自动换行
            bg=self.text_bg,
            fg=self.text_fg,
            insertbackground=self.text_fg,  # 光标颜色
            selectbackground="#a6d2ff",  # 选中文本的背景色
            selectforeground=self.text_fg,  # 选中文本的前景色
            font=("Consolas", 11),  # 设置等宽字体
            padx=5,
            pady=5,
            cursor="xterm"  # 设置默认文本光标
        )
        self.text_area.pack(side=tk.LEFT, expand=True, fill='both')
        
        # 将行号与文本区域关联
        self.line_numbers.attach(self.text_area)
        
        # 整合所有事件绑定
        self.text_area.bind("<<Change>>", self.on_text_change)  # 文本变化事件
        self.text_area.bind("<Configure>", self.on_configure)   # 窗口大小变化事件
        self.text_area.bind("<Motion>", self.update_cursor_for_url)  # 鼠标移动
        self.text_area.bind("<KeyRelease>", self.update_status)  # 键盘释放
        self.text_area.bind("<ButtonRelease-1>", self.update_status)  # 鼠标点击释放
        
        # 创建垂直滚动条
        self.scrollbar = ttk.Scrollbar(self.text_frame, orient="vertical", 
                                     command=self.text_area.yview)
        self.scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.text_area.configure(yscrollcommand=self.scrollbar.set)
        
        # 创建状态栏
        self.status_bar = tk.Frame(self.main_frame, bg=self.bg_color, height=25)
        self.status_bar.pack(side=tk.BOTTOM, fill=tk.X)
        self.status_bar.pack_propagate(0)  # 固定状态栏高度
        
        # 编码标签
        self.encoding_label = tk.Label(
            self.status_bar,
            text="编码: UTF-8",
            bg=self.bg_color,
            fg=self.text_fg,
            anchor=tk.W,
            font=("微软雅黑", 9)
        )
        self.encoding_label.pack(side=tk.LEFT, padx=5)
        
        # 分隔符
        tk.Label(
            self.status_bar,
            text="|",
            bg=self.bg_color,
            fg=self.text_fg,
            font=("微软雅黑", 9)
        ).pack(side=tk.LEFT, padx=5)
        
        # 文件大小标签
        self.file_size_label = tk.Label(
            self.status_bar,
            text="大小: 0 B",
            bg=self.bg_color,
            fg=self.text_fg,
            font=("微软雅黑", 9)
        )
        self.file_size_label.pack(side=tk.LEFT, padx=5)
        
        # 分隔符
        tk.Label(
            self.status_bar,
            text="|",
            bg=self.bg_color,
            fg=self.text_fg,
            font=("微软雅黑", 9)
        ).pack(side=tk.LEFT, padx=5)
        
        # 光标位置标签
        self.position_label = tk.Label(
            self.status_bar,
            text="第 1 行，第 1 列",
            bg=self.bg_color,
            fg=self.text_fg,
            font=("微软雅黑", 9)
        )
        self.position_label.pack(side=tk.LEFT, padx=5)
        
        # 分隔符
        tk.Label(
            self.status_bar,
            text="|",
            bg=self.bg_color,
            fg=self.text_fg,
            font=("微软雅黑", 9)
        ).pack(side=tk.LEFT, padx=5)
        
        # 字符数标签
        self.char_count_label = tk.Label(
            self.status_bar,
            text="字符数: 0",
            bg=self.bg_color,
            fg=self.text_fg,
            font=("微软雅黑", 9)
        )
        self.char_count_label.pack(side=tk.LEFT, padx=5)
        
        # 分隔符
        tk.Label(
            self.status_bar,
            text="|",
            bg=self.bg_color,
            fg=self.text_fg,
            font=("微软雅黑", 9)
        ).pack(side=tk.LEFT, padx=5)
        
        # 最后修改时间标签
        self.modified_time_label = tk.Label(
            self.status_bar,
            text="修改时间: --",
            bg=self.bg_color,
            fg=self.text_fg,
            font=("微软雅黑", 9)
        )
        self.modified_time_label.pack(side=tk.LEFT, padx=5)
        
        # 创建菜单栏样式
        self.menu_bar = tk.Menu(self.root)
        self.root.config(menu=self.menu_bar)
        
        # 文件菜单
        self.file_menu = tk.Menu(
            self.menu_bar,
            tearoff=0,
            cursor="hand2",
            bg=self.text_bg,
            fg=self.text_fg,
            activebackground="#e1f0ff",
            activeforeground=self.text_fg
        )
        self.menu_bar.add_cascade(label="文件", menu=self.file_menu)
        self.file_menu.add_command(label="新建", command=self.new_file, accelerator="Ctrl+N")
        self.file_menu.add_command(label="打开", command=self.open_file, accelerator="Ctrl+O")
        self.file_menu.add_command(label="保存", command=self.save_file, accelerator="Ctrl+S")
        self.file_menu.add_command(label="另存为", command=self.save_as, accelerator="Ctrl+Shift+S")
        self.file_menu.add_separator()
        self.file_menu.add_command(label="打开文件所在位置", command=self.open_file_location)
        self.file_menu.add_separator()
        self.file_menu.add_command(label="退出", command=self.on_closing, accelerator="Alt+F4")
        
        # 编辑菜单
        self.edit_menu = tk.Menu(
            self.menu_bar,
            tearoff=0,
            cursor="hand2",
            bg=self.text_bg,
            fg=self.text_fg,
            activebackground="#e1f0ff",
            activeforeground=self.text_fg
        )
        self.menu_bar.add_cascade(label="编辑", menu=self.edit_menu)
        self.edit_menu.add_command(label="剪切", command=lambda: self.text_area.event_generate("<<Cut>>"), accelerator="Ctrl+X")
        self.edit_menu.add_command(label="复制", command=lambda: self.text_area.event_generate("<<Copy>>"), accelerator="Ctrl+C")
        self.edit_menu.add_command(label="粘贴", command=lambda: self.text_area.event_generate("<<Paste>>"), accelerator="Ctrl+V")
        self.edit_menu.add_separator()
        self.edit_menu.add_command(label="查找和替换", command=self.show_find_replace, accelerator="Ctrl+F")
        
        # 添加关于菜单
        self.about_menu = tk.Menu(
            self.menu_bar,
            tearoff=0,
            cursor="hand2",
            bg=self.text_bg,
            fg=self.text_fg,
            activebackground="#e1f0ff",
            activeforeground=self.text_fg
        )
        self.menu_bar.add_cascade(label="关于", menu=self.about_menu)
        self.about_menu.add_command(label="关于码界轩记事本", command=self.show_about)
        
        # 为菜单栏标签添加鼠标样式
        for child in self.menu_bar.winfo_children():
            child.bind('<Enter>', lambda e: e.widget.configure(cursor='hand2'))
            child.bind('<Leave>', lambda e: e.widget.configure(cursor=''))
        
        # 为状态栏添加鼠标样式
        self.encoding_label.bind('<Enter>', lambda e: e.widget.configure(cursor='hand2'))
        self.encoding_label.bind('<Leave>', lambda e: e.widget.configure(cursor=''))
        
        # 绑定快捷键
        self.root.bind('<Control-n>', lambda e: self.new_file())
        self.root.bind('<Control-o>', lambda e: self.open_file())
        self.root.bind('<Control-s>', lambda e: self.save_file())
        self.root.bind('<Control-Shift-S>', lambda e: self.save_as())
        self.root.bind('<Control-f>', lambda e: self.show_find_replace())
        
        self.current_file = None
        self.current_encoding = 'utf-8'
        self.is_modified = False  # 添加修改状态标记
        
        # 用于保存查找位置
        self.last_find_pos = "1.0"
        
        # 创建主文本区域后添加以下代码：
        self.text_area.tag_configure("found", background="#fff2a8")  # 浅黄色背景
        
        # 创建主文本区域后添加URL标签配置
        self.text_area.tag_configure("url", 
            foreground="#0066cc",     # 淡蓝色
            underline=True,           # 下划线
            font=("Consolas", 11)     # 保持与普通文本相同的字体
        )
        
        # 创建提示框
        self.url_tooltip = tk.Label(
            self.root,
            text="按住 Ctrl + 点击 打开链接",
            bg="#FFFFD1",
            fg="#333333",
            relief="solid",
            borderwidth=1,
            font=("微软雅黑", 9),
            padx=5,
            pady=3
        )
        
        # 跟踪Ctrl键状态
        self.ctrl_pressed = False
        self.root.bind("<KeyPress-Control_L>", lambda e: self.set_ctrl_state(True))
        self.root.bind("<KeyRelease-Control_L>", lambda e: self.set_ctrl_state(False))
        self.root.bind("<KeyPress-Control_R>", lambda e: self.set_ctrl_state(True))
        self.root.bind("<KeyRelease-Control_R>", lambda e: self.set_ctrl_state(False))
        self.root.bind("<FocusOut>", lambda e: self.set_ctrl_state(False))
        
        # 绑定窗口关闭事件
        self.root.protocol("WM_DELETE_WINDOW", self.on_closing)
        
    def center_window(self):
        """将窗口居中显示"""
        # 获取屏幕宽度和高度
        screen_width = self.root.winfo_screenwidth()
        screen_height = self.root.winfo_screenheight()
        
        # 获取窗口宽度和高度
        window_width = 800
        window_height = 600
        
        # 计算居中位置
        center_x = int((screen_width - window_width) / 2)
        center_y = int((screen_height - window_height) / 2)
        
        # 设置窗口位置
        self.root.geometry(f"{window_width}x{window_height}+{center_x}+{center_y}")
        
    def detect_encoding(self, file_path):
        """检测文件编码"""
        with open(file_path, 'rb') as file:
            raw_data = file.read()
            result = chardet.detect(raw_data)
            return result['encoding']
    
    def new_file(self):
        self.text_area.delete(1.0, tk.END)
        self.current_file = None
        self.is_modified = False
        self.update_title()
        
    def open_file(self):
        file_path = filedialog.askopenfilename(
            defaultextension=".txt",
            filetypes=[("文本文件", "*.txt"), ("所有文件", "*.*")]
        )
        if file_path:
            try:
                # 检测文件编码
                detected_encoding = self.detect_encoding(file_path)
                if detected_encoding:
                    self.current_encoding = detected_encoding
                else:
                    self.current_encoding = 'utf-8'
                
                # 使用检测到的编码打开文件
                with open(file_path, 'r', encoding=self.current_encoding) as file:
                    self.text_area.delete(1.0, tk.END)
                    self.text_area.insert(1.0, file.read())
                self.current_file = file_path
                self.is_modified = False
                self.update_title()
                self.encoding_label.config(text=f"编码: {self.current_encoding.upper()}")
                self.update_file_info()  # 更新文件信息
            except Exception as e:
                messagebox.showerror("错误", f"无法打开文件: {str(e)}")
                
    def save_file(self):
        if self.current_file:
            try:
                content = self.text_area.get(1.0, tk.END)
                with open(self.current_file, 'w', encoding=self.current_encoding) as file:
                    file.write(content)
                self.is_modified = False
                self.update_title()
                self.update_file_info()  # 更新文件信息
            except Exception as e:
                messagebox.showerror("错误", f"无法保存文件: {str(e)}")
        else:
            self.save_as()
            
    def save_as(self):
        file_path = filedialog.asksaveasfilename(
            defaultextension=".txt",
            filetypes=[("文本文件", "*.txt"), ("所有文件", "*.*")]
        )
        if file_path:
            try:
                content = self.text_area.get(1.0, tk.END)
                with open(file_path, 'w', encoding=self.current_encoding) as file:
                    file.write(content)
                self.current_file = file_path
                self.is_modified = False
                self.update_title()
                self.update_file_info()  # 更新文件信息
            except Exception as e:
                messagebox.showerror("错误", f"无法保存文件: {str(e)}")

    def on_text_change(self, event=None):
        """文本变化时的处理"""
        # 设置修改状态
        if not self.is_modified:
            self.is_modified = True
            self.update_title()
        
        # 更新状态栏
        self.update_status()
        # 更新URL高亮
        self.highlight_urls()
        # 更新行号
        self.line_numbers.redraw()

    def on_configure(self, event=None):
        """窗口大小改变时的处理"""
        # 更新行号
        self.line_numbers.redraw()

    def show_about(self):
        """显示关于对话框"""
        about_window = tk.Toplevel(self.root)
        about_window.title("关于码界轩记事本")
        about_window.geometry("300x200")
        # 设置模态窗口（不能操作主窗口）
        about_window.grab_set()
        # 设置窗口图标
        try:
            icon_path = get_icon_file()
            about_window.iconbitmap(icon_path)
        except:
            pass
        # 固定窗口大小
        about_window.resizable(False, False)
        
        # 设置窗口在主窗口中央
        about_window.transient(self.root)
        about_x = self.root.winfo_x() + (self.root.winfo_width() - 300) // 2
        about_y = self.root.winfo_y() + (self.root.winfo_height() - 200) // 2
        about_window.geometry(f"300x200+{about_x}+{about_y}")
        
        # 创建内容框架
        frame = tk.Frame(about_window, bg=self.bg_color)
        frame.pack(expand=True, fill='both', padx=20, pady=20)
        
        # 显示图标
        try:
            icon = tk.PhotoImage(file='mjx128.ico')
            icon_label = tk.Label(frame, image=icon, bg=self.bg_color)
            icon_label.image = icon  # 保持引用
            icon_label.pack(pady=(0, 10))
        except:
            # 如果无法加载ico文件，跳过图标显示
            pass
        
        # 显示名称
        name_label = tk.Label(
            frame,
            text="码界轩记事本",
            font=("微软雅黑", 12, "bold"),
            bg=self.bg_color,
            fg=self.text_fg
        )
        name_label.pack(pady=5)
        
        # 显示作者
        author_label = tk.Label(
            frame,
            text="作者：陈佳宝",
            font=("微软雅黑", 10),
            bg=self.bg_color,
            fg=self.text_fg
        )
        author_label.pack(pady=2)
        
        # 显示版本号
        version_label = tk.Label(
            frame,
            text="版本号：1.0.0",
            font=("微软雅黑", 10),
            bg=self.bg_color,
            fg=self.text_fg
        )
        version_label.pack(pady=2)
        
        # 显示网址（可点击）
        url = "https://chenjiabao.com"
        url_label = tk.Label(
            frame,
            text=url,
            font=("微软雅黑", 10, "underline"),
            bg=self.bg_color,
            fg="#0066cc",
            cursor="hand2"
        )
        url_label.pack(pady=2)
        url_label.bind("<Button-1>", lambda e: webbrowser.open(url))
        
        # 添加确定按钮
        ok_button = tk.Button(
            frame,
            text="确定",
            command=about_window.destroy,
            bg=self.text_bg,
            fg=self.text_fg,
            relief="groove",
            cursor="hand2"
        )
        ok_button.pack(pady=(10, 0))

    def update_status(self, event=None):
        """更新状态栏信息"""
        # 更新光标位置
        cursor_position = self.text_area.index(tk.INSERT)
        line, column = cursor_position.split('.')
        self.position_label.config(text=f"第 {line} 行，第 {int(column)+1} 列")
        
        # 更新字符数
        content = self.text_area.get(1.0, tk.END)
        char_count = len(content) - 1  # 减去最后的换行符
        self.char_count_label.config(text=f"字符数: {char_count}")

    def show_find_replace(self):
        """显示查找替换对话框"""
        find_window = tk.Toplevel(self.root)
        find_window.title("查找和替换")
        find_window.geometry("400x200")
        find_window.iconbitmap('mjx128.ico')
        find_window.resizable(False, False)
        
        # 设置窗口在主窗口中央
        find_window.transient(self.root)
        find_x = self.root.winfo_x() + (self.root.winfo_width() - 400) // 2
        find_y = self.root.winfo_y() + (self.root.winfo_height() - 200) // 2
        find_window.geometry(f"400x200+{find_x}+{find_y}")
        
        # 创建主框架
        main_frame = tk.Frame(find_window, bg=self.bg_color)
        main_frame.pack(expand=True, fill='both', padx=20, pady=20)
        
        # 查找框
        find_frame = tk.Frame(main_frame, bg=self.bg_color)
        find_frame.pack(fill='x', pady=(0, 10))
        tk.Label(find_frame, text="查找内容:", bg=self.bg_color).pack(side=tk.LEFT)
        find_entry = tk.Entry(find_frame, width=30)
        find_entry.pack(side=tk.LEFT, padx=5)
        
        # 替换框
        replace_frame = tk.Frame(main_frame, bg=self.bg_color)
        replace_frame.pack(fill='x', pady=(0, 10))
        tk.Label(replace_frame, text="替换为:", bg=self.bg_color).pack(side=tk.LEFT)
        replace_entry = tk.Entry(replace_frame, width=30)
        replace_entry.pack(side=tk.LEFT, padx=5)
        
        # 选项框架
        options_frame = tk.Frame(main_frame, bg=self.bg_color)
        options_frame.pack(fill='x', pady=(0, 10))
        case_var = tk.BooleanVar()
        case_check = tk.Checkbutton(options_frame, text="区分大小写", 
                                   variable=case_var, bg=self.bg_color)
        case_check.pack(side=tk.LEFT)
        
        # 按钮框架
        button_frame = tk.Frame(main_frame, bg=self.bg_color)
        button_frame.pack(fill='x')
        
        def find_next():
            self.find_text(find_entry.get(), case_var.get())
            
        def replace():
            if self.text_area.tag_ranges("sel"):
                self.text_area.delete("sel.first", "sel.last")
                self.text_area.insert("insert", replace_entry.get())
                # 替换后自动查找下一处
                find_next()
            else:
                # 如果没有选中文本，先查找
                find_next()
            
        def replace_all():
            content = self.text_area.get("1.0", "end-1c")  # 不包含最后的换行符
            find_text = find_entry.get()
            replace_text = replace_entry.get()
            
            if not find_text:
                return
                
            if not case_var.get():
                # 不区分大小写时，使用正则表达式
                import re
                pattern = re.compile(re.escape(find_text), re.IGNORECASE)
                new_content, count = pattern.subn(replace_text, content)
            else:
                # 区分大小写时，直接替换
                new_content = content.replace(find_text, replace_text)
                count = content.count(find_text)
            
            if count > 0:
                self.text_area.delete("1.0", tk.END)
                self.text_area.insert("1.0", new_content)
                messagebox.showinfo("替换完成", f"共完成 {count} 处替换")
            else:
                messagebox.showinfo("替换", "找不到要替换的内容")
        
        # 添加按钮
        tk.Button(button_frame, text="查找下一个", command=find_next,
                 bg=self.text_bg, fg=self.text_fg).pack(side=tk.LEFT, padx=5)
        tk.Button(button_frame, text="替换", command=replace,
                 bg=self.text_bg, fg=self.text_fg).pack(side=tk.LEFT, padx=5)
        tk.Button(button_frame, text="全部替换", command=replace_all,
                 bg=self.text_bg, fg=self.text_fg).pack(side=tk.LEFT, padx=5)
        tk.Button(button_frame, text="关闭", command=find_window.destroy,
                 bg=self.text_bg, fg=self.text_fg).pack(side=tk.LEFT, padx=5)
        
        # 设置焦点到查找输入框
        find_entry.focus_set()
        
        # 如果有选中的文本，自动填入查找框
        if self.text_area.tag_ranges("sel"):
            find_entry.insert(0, self.text_area.get("sel.first", "sel.last"))
            
    def find_text(self, find_str, case_sensitive=False):
        """查找文本"""
        if not find_str:
            return
            
        # 清除之前的高亮
        self.text_area.tag_remove("found", "1.0", "end")
        
        # 获取起始位置
        start_pos = self.text_area.index("insert")
        
        # 如果当前位置与上次查找位置相同，从下一个字符开始
        if start_pos == self.last_find_pos:
            start_pos = self.text_area.index(f"{start_pos}+1c")
            
        # 获取要搜索的内容
        content = self.text_area.get("1.0", "end")
        search_text = find_str
        
        if not case_sensitive:
            content = content.lower()
            search_text = find_str.lower()
            
        # 从当前位置到末尾查找
        start_idx = self.text_area.count("1.0", start_pos, "chars")[0]
        pos = content.find(search_text, start_idx)
        
        if pos == -1:  # 如果没找到，从头开始找
            pos = content.find(search_text, 0, start_idx)
            
        if pos >= 0:
            # 计算找到的位置
            line_count = content.count('\n', 0, pos)
            line_start = content.rfind('\n', 0, pos)
            if line_start == -1:
                line_start = 0
            else:
                line_start += 1
            char_in_line = pos - line_start
            
            # 设置位置
            find_pos = f"{line_count + 1}.{char_in_line}"
            end_pos = f"{line_count + 1}.{char_in_line + len(find_str)}"
            
            # 移动到找到的位置并选中
            self.text_area.tag_remove("sel", "1.0", "end")
            self.text_area.tag_add("sel", find_pos, end_pos)
            self.text_area.tag_add("found", find_pos, end_pos)
            self.text_area.mark_set("insert", end_pos)
            self.text_area.see(find_pos)
            self.last_find_pos = find_pos
        else:
            messagebox.showinfo("查找", "找不到指定内容！")
            self.last_find_pos = "1.0"

    def open_file_location(self):
        """在资源管理器中打开当前文件所在位置"""
        if self.current_file:
            # 获取文件所在目录
            file_dir = os.path.dirname(os.path.abspath(self.current_file))
            try:
                # 直接打开文件所在目录
                os.startfile(file_dir)
            except Exception as e:
                messagebox.showerror("错误", f"无法打开文件位置: {str(e)}")
        else:
            messagebox.showinfo("提示", "请先打开或保存文件")

    def highlight_urls(self, event=None):
        """高亮显示URL链接"""
        import re
        
        # 清除现有的URL标签
        self.text_area.tag_remove("url", "1.0", "end")
        
        # URL匹配模式
        url_pattern = r'https?://(?:[-\w.]|(?:%[\da-fA-F]{2}))+'
        
        # 获取所有文本
        content = self.text_area.get("1.0", "end-1c")
        
        # 查找所有URL
        for match in re.finditer(url_pattern, content):
            start_idx = match.start()
            end_idx = match.end()
            
            # 计算行号和列号
            start_line = content.count('\n', 0, start_idx) + 1
            end_line = content.count('\n', 0, end_idx) + 1
            
            if start_line == end_line:
                # 如果URL在同一行
                start_col = start_idx - content.rfind('\n', 0, start_idx) - 1
                if start_col < 0: start_col = start_idx
                end_col = end_idx - content.rfind('\n', 0, end_idx) - 1
                if end_col < 0: end_col = end_idx
            else:
                # 如果URL跨行（罕见情况）
                start_col = start_idx - content.rfind('\n', 0, start_idx) - 1
                if start_col < 0: start_col = start_idx
                end_col = end_idx - content.rfind('\n', 0, end_idx) - 1
                if end_col < 0: end_col = end_idx
            
            # 添加URL标签
            start = f"{start_line}.{start_col}"
            end = f"{end_line}.{end_col}"
            self.text_area.tag_add("url", start, end)
            
            # 为每个URL添加点击事件
            self.text_area.tag_bind("url", "<Button-1>", 
                lambda e, url=match.group(): self.handle_url_click(e, url))
    
    def handle_url_click(self, event, url):
        """处理URL点击事件"""
        if self.ctrl_pressed:
            webbrowser.open(url)

    def update_cursor_for_url(self, event=None):
        """更新鼠标指针样式和提示框"""
        try:
            tags = self.text_area.tag_names("current")
            
            if "url" in tags:
                # 只在按下Ctrl时显示手型光标和隐藏提示
                if self.ctrl_pressed:
                    if self.text_area.cget("cursor") != "hand2":  # 只在需要时改变
                        self.text_area.config(cursor="hand2")
                    self.url_tooltip.place_forget()
                else:
                    # 不按Ctrl时显示提示框，保持默认光标
                    x = self.root.winfo_pointerx() - self.root.winfo_rootx() + 15
                    y = self.root.winfo_pointery() - self.root.winfo_rooty() + 10
                    self.url_tooltip.place(x=x, y=y)
            else:
                # 移出URL区域时，如果当前是手型光标才改回默认
                if self.text_area.cget("cursor") == "hand2":
                    self.text_area.config(cursor="xterm")
                self.url_tooltip.place_forget()
        except:
            self.url_tooltip.place_forget()
    
    def set_ctrl_state(self, state):
        """设置Ctrl键状态"""
        self.ctrl_pressed = state
        self.update_cursor_for_url()

    def update_title(self):
        """更新窗口标题"""
        if self.current_file:
            title = f"码界轩记事本 - {os.path.basename(self.current_file)}"
        else:
            title = "码界轩记事本"
        
        if self.is_modified:
            title += "*"
        
        self.root.title(title)

    def on_closing(self):
        """处理窗口关闭事件"""
        if self.is_modified:
            if self.current_file:
                message = f"是否将更改保存到\n{self.current_file}?"
            else:
                message = "是否将更改保存到未命名文件?"
            
            answer = messagebox.askyesnocancel(
                "保存文件",
                message,
                icon='warning'
            )
            
            if answer is True:  # 用户选择"是"
                if self.current_file:
                    self.save_file()
                else:
                    self.save_as()
                if not self.is_modified:  # 保存成功
                    self.root.destroy()
            elif answer is False:  # 用户选择"否"
                self.root.destroy()
            # 用户选择"取消"，不做任何操作
        else:
            self.root.destroy()

    def update_file_info(self):
        """更新文件信息"""
        if self.current_file and os.path.exists(self.current_file):
            # 获取文件大小
            size = os.path.getsize(self.current_file)
            if size < 1024:
                size_str = f"{size} B"
            elif size < 1024 * 1024:
                size_str = f"{size/1024:.1f} KB"
            else:
                size_str = f"{size/(1024*1024):.1f} MB"
            
            # 获取最后修改时间
            mtime = os.path.getmtime(self.current_file)
            time_str = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(mtime))
            
            # 更新标签
            self.file_size_label.config(text=f"大小: {size_str}")
            self.modified_time_label.config(text=f"修改时间: {time_str}")
        else:
            # 如果没有文件，显示默认值
            self.file_size_label.config(text="大小: 0 B")
            self.modified_time_label.config(text="修改时间: --")

if __name__ == "__main__":
    root = tk.Tk()
    notepad = Notepad(root)
    
    # 如果有命令行参数（文件路径），则打开该文件
    if len(sys.argv) > 1:
        file_path = sys.argv[1]
        try:
            # 检测文件编码
            detected_encoding = notepad.detect_encoding(file_path)
            if detected_encoding:
                notepad.current_encoding = detected_encoding
            else:
                notepad.current_encoding = 'utf-8'
            
            # 使用检测到的编码打开文件
            with open(file_path, 'r', encoding=notepad.current_encoding) as file:
                notepad.text_area.delete(1.0, tk.END)
                notepad.text_area.insert(1.0, file.read())
            notepad.current_file = file_path
            notepad.is_modified = False
            notepad.update_title()
            notepad.encoding_label.config(text=f"编码: {notepad.current_encoding.upper()}")
        except Exception as e:
            messagebox.showerror("错误", f"无法打开文件: {str(e)}")
    
    root.mainloop() 